Beginners Programming Series VII

Part 1 - Windows, Dice and a Little Math Too..

© 2004, Brad Moore

author contact:

http://www.freewebz.com/lb-connection

Home

Tip Corner: Using

Game Programming

Round Buttons

Rotating Objects

LBW: Book Marks

Slide Puzzle

Speech DLL

Addresses

Beginners Programming

Newsletter help

Index


Hey! Your back...

Welcome to the continuing mini-series on Beginning Programming with Liberty Basic. We are making our way through the process of learning the Liberty Basic language, programming concepts and how to think like a programmer. These things come to people in varying rates, so do not feel bad if you are still struggling to grasp where we are and how we got here. However, if you are feeling this way, you do need to spend some time going back over the past articles in this series. May I also encourage everyone to spend some time in the Liberty Basic help file and some time trying to complete the tutorials that come with Liberty Basic.

New this year (it is the beginning of 2004) is the recently released Liberty Basic version 4. It features the all new Leason Browser which gives an excellent presentation of the Liberty Basic tutorial. Even if you are not planning to upgrade just yet (I know you will want to some day), I recommend downloading the version 4 product just to work through those tutorials. Also note that the code being developed for this series is for Liberty Basic version 3.x, and (although not tested for it) should run without problems on version 4 as well.

Like previous articles in this series, we will be maintaining the Glossary. Items that are explained in better detail in the Glossary are highlighted in the text and linked back to the Glossary page.

Catching Our Breath

We really covered a lot of ground last time, completing the StarQuest game and introducing Windows and graphics. I feel reading over it that much of the explanations we not as clear as they could have been regarding the operation of Windows and the graphics commands. The fact is, there is a lot of material there, and it is hard to simplify it enough for initial presentation. If it all left your head spinning a little, please accept my apology - I will recap the material again in hopes of building a stronger foundation. We will use this foundation to introduce buttons and begin to build a graphic dice rolling program.

Last time we introduced Windows, which are simply containers for displaying the user interface of a program to the user. We often call these forms in programming vernacular. At the moment we are coding our forms by hand, but Liberty Basic comes with a tool called FreeForm that can assist greatly in the creation of forms, and the automatic generation of Basic code needed to produce the form. Learn More about FreeForm in the Glossary. Also read David Drake's great set of articles on using FreeForm and forms in general in issue 86 (2/2001) [http://babek.info/libertybasicfiles/lbnews/nl92/eightysix.html].

We saw that the command to create (or open) a window is OPEN. We examined the format of that command, looking in depth at each of the arguments in the command. Here is a brief overview. The following command opens a Graphics type window with the style of no scroll bars:

Open "My Graphics Window" for graphics_nsb as #main

Let's look a bit closer - obviously the first element of the command is the Key Word OPEN itself. According to the help file there are three arguments that follow the key word.

Window Title - this is a string (either a sting literal or a string variable) that contains the text we want to have displayed in the windows titlebar. In our case the window will display "My Graphics Window" in the titlebar as such:

Note that this is a required argument, but you can pass an empty string if you want the titlebar to be blank.

Window Type - This is the type of window you are opening. The argument always begins with "for" and then the actual window type. There are several different types of windows, and they are further broken down into subgroups by the window modifiers. The window types used most commonly are GRAPHICS and WINDOW. The common modifiers do things like removing scroll bars, frames, making the windows so they can not be resized and opening windows full screen. Here are the various subgroups for the GRAPHICS and WINDOW type windows:

graphics            open a graphics window
graphics_fs         open a graphics window full screen (size of the screen)
graphics_nsb        open a graphics window w/no scroll bars
graphics_fs_nsb     open a graphics window full screen, w/no scroll bars
graphics_nf_nsb     open a graphics window with no sizing frame or scroll bars

window              open a basic window type
window_nf           open a basic window type without a sizing frame
window_popup        open a window without a titlebar

Handle - Finally we have the window's handle - it is a name that the programmer gives the window for reference elsewhere in the code. Handles always begin with a pound sign ("#") followed by an alpha-numeric name. Handles are not enclosed in quotes, and until Liberty Basic 4 could not be represented by a variable (we will examine that in another article). The word "as" always precedes the handle name. Although there is no specific rule regarding the name you give your window, most programmers tend to use "#main" for the initial main program window.

In addition to actually opening the window, we discussed some of the other Basic commands we can use to adjust the window properties. These included the Liberty Basic global variables WindowHeight and WindowWidth, which are used to define the size of the window; as well as the global variables UpperLeftX and UpperLeftY which control the placement of the window on the screen.

In the work we did last time we opened a short, fairly wide window of the type GRAPHICS and later displayed six dice in it. Here is the code we used to open the window:

NOMAINWIN
WindowWidth = 740
WindowHeight = 160
UpperLeftX = 40
UpperLeftY = 40

Open "Show Dice" for Graphics_nsb as #main

Don't forget that the NOMAINWIN command simply tells Liberty Basic that we do not need the main console window opened up. This is the text based window that we have been working in during most of the preceding installments of this series.

There are a few additional things that need done to get this window ready for use by the program we were writing. We accomplished these using the next three commands:

    #main "trapclose [quit]"
    #main "down; fill white; up; flush"
    #main "font ms_sans_serif 10"

All three of these commands are directed at the window we opened. They MUST follow the OPEN command to correctly reference the window object. Each command begins with the window handle. In the old days (back in Liberty Basic 2.x and earlier) we were required to PRINT these commands to the window using the PRINT command. The commands are actually still being printed to the window; the PRINT command is simply understood, and not required. The following code would work also:

    Print #main, "trapclose [quit]"
    Print #main, "down; fill white; up; flush"
    Print #main, "font ms_sans_serif 10"

So the parts of the commands in quotes are really the unique commands that are being directed to the window. Last time we simply told you that you needed these commands, now let's look at what they actually do.

The first command issued is the TRAPCLOSE command. This is a special command that is able to redirect the execution of the program in the case of a special event. What does that mean?

As you will recall, Liberty Basic executes the code from top to bottom, one line at a time until it comes to some kind of branch or goto causing the execution to be diverted to another portion of code. In the case of the TRAPCLOSE command, the program execution will be diverted as if there were a goto statement when the user closes the window by clicking the "X" icon in the upper right corner of the window.

The program execution is diverted to the label that follows the command. In the case of out example, to a unit of code that begins with the label [quit]. It is important to note that this is an event, and events can only be detected when the program execution reaches a WAIT, INPUT or SCAN command. We will touch on this in just a little more detail when we examine command buttons, shortly.

The next line of code that is printed to the window performs some basic formatting to the graphics area of the window. They are graphics commands. The first puts the Pen down so that subsequent commands will take effect, the next fills the entire graphics area with the color white, next the pen is lifted, and finally the FLUSH command is issued.

Lets discuss flushing the graphics commands for a second. The topic can really become complex, because it leads to the concept of graphics segments and graphic segment management and clean up. We will leave the latter portion of the discussion for another time. Just be aware that when you flush your graphics commands you are consuming actual system resources in the form of memory. Memory is finite, and a lot of graphics drawn and flushed without proper management can lead to low memory conditions and problems with your program. As I said we will address this in a later installment of this series, but if you would like to get a head start on the subject, please read Alyce Watson's excellent article SEGMENTS AND FLUSHING in the Liberty Basic newsletter, issue 102 [http://babek.info/libertybasicfiles/lbnews/nl102/4.htm].

Back to flushing. The FLUSH command basically makes the graphics commands that have been executed (since the last FLUSH) stick to the graphics window or graphicsbox. If you do not flush the graphics commands, and another window should come to the forefront and cover your graphics window - it will destroy your "unflushed" graphics. This is evident when the offending window is moved aside and you find all the "unflushed" graphics erased from the area that was covered. This is because Liberty Basic does not know it is suppose to redraw these graphics in these cases until you flush the graphics commands.

The last command sets the default font face and size for the window. It is a convienent command to include as it insures that your program will look the same on other peoples PC's as it does on yours. I will let the Liberty Basic Helpfile do the talking here:

    print #handle, "font facename pointSize"

Set the pen's font to the specified face and point size. If an exact match cannot be found, then Liberty BASIC will try to find a close match, with size being of more prominence than face. For more on specifying fonts read How to Specify Fonts (in the Helpfile)

I really recommend reading more about fonts in the "How to Specify Fonts" section as well as it contains excellent information about using the various font commands in Liberty Basic.

Drawing Dice

If you will recall from last time we were working on drawing dice using some of Liberty Basic graphics commands. We had drawn six square boxes across the graphics window we had opened up, and I had developed the code to draw four of the six possible faces. Let's recap the commands a little, and then I will share my code for drawing all six faces.

All the drawing commands we are about to review conform to the style of usage as shown above, specifically, the commands must be sent to a graphicsbox or window using the PRINT command (or its implied syntax). The object to receive the command (either a graphicsbox or a graphics window) must be called out in the command using its handle. We have not yet worked with graphicsboxes, so all of our code shown related to graphics windows. Using these commands on a graphicsbox is nearly the same process, but for simplicity, we will cover that in a future article.

The commands used last time were: GOTO, DOWN, UP, BOX, CIRCLEFILLED and BACKCOLOR. A brief recap of the operation of each of these commands is in order - caution, I describe how the command works below, but I do not give its syntax - check it out in the help file, in the previous installment of this series or simply check out the code.

Fundamental to the understanding of drawing graphics in Liberty Basic is the PEN. As discussed last time, the model adopted for the graphics commands conforms roughly to that of LOGO or Turtle graphics of the early 1980's. In all cases an imaginary PEN is required to produce graphics on the screen. Additionally, the PEN must be down (an in some cases moving) in order to actually produce visible output. The graphics commands UP and DOWN effect the PEN's status: UP removes the PEN from the screen and allows the PEN to be moved about at will without causing its movements to be drawn on the screen. Likewise, DOWN lowers the PEN to the screen and thereafter will cause graphics to be drawn on the screen.

GOTO - moves the pen to the location specified. The coordinates are given in absolute referencing, meaning they are measured in pixels from the upper left corner of the window (or graphicsbox). If the pen is DOWN, then a line will be draw as the pen is moved.

BOX - draws a box between the current pen location and the coordinates specified. The coordinates are again specified using absolute referencing. The pen must be DOWN to actually produce a box on the screen.

CIRCLEFILLED - this command is similar to the box command, in that it creates a circle from the current pen location. Instead of specifying a second set of coordinates, you only need to specify the radius of the circle. Remember folks - the radius is half the diameter (or width) of the circle. If you want a 12 pixel wide circle you need to specify a radius of six. The center of the circle will be the current pen location. This command will cause the circle to be filled with the current drawing background color. Again, the pen must be DOWN in order to produce the circle on the screen.

BACKCOLOR - this command sets the current color used to draw figures that are filled with a color, such as in the CIRCLEFILLED command. The command can be issued anytime you wish to change the color used to fill a drawn figure. Issuing the command after drawing filled figures does not alter their color, it is only effective on figures yet to be drawn.

A Little Afternoon Math -

We discussed the layout of the first dice in the previous installment of the series by showing the following graphic:

In this graphic we explain the placement of each of the filled circles in the dice outline in relationship to the dice. Notice that a symmetrical pattern is present. Each dice is surrounded by a 20 pixel buffer, it is 15 pixels to the center of the first dot (which is represented by a filled circle), then 25 to the center dot - in both the up/down direction and the left/right direction. Then again another 25 pixels to the next series of dots, and then another 15 to the edge of the dice.

This pattern is repeated in the next dice, but the starting position of the upper left corner of this dice is 120 pixels from the starting point of the first dice (15+25+25+15+20+20=120). Also notice that it is 140 pixels from the upper left corner of the graphics window (120+20=140). That means that we will need to specify the next set of dots (filled circles) with an offset of 140 pixels, as compared to the first dice.

Of course the first dice only needs one dot, right in the center. We calculate the location of that dot relative to upper left corner of the window as:

   X: 20 + 15 + 25 = 60
   Y: 20 + 15 + 25 = 60

So we know we can get our 10 pixel wide filled circle drawn right where we want it by first moving the pen (don't forget to lift it) to the center of the circle which we calculated as being at 60,60. We use the following string of commands (don't forget, you can string a series of graphics commands together in a single quote string, each separated by a semi-colon):

    #main, "up; goto 60 60, down, circlefilled 5"

For the command to have produced a black dot, we would have had to issue the BACKCOLOR command first.

So, lets look at the math need to calculate the location of the two dots need to depict a dice with a two on it. This will be drawn on the second dice, which we know has an offset of 140 pixels in the X direction. Also these dots are one in the upper left portion and another in the lower right portion - a bit tricky.

First the dot in the upper left:

   X: 140 + 15 = 155
   Y: 20 + 15 = 35

Now the dot in the lower right:

   X: 140 + 15 + 25 + 25 = 205
   Y: 20 + 15 + 25 +25 = 85

We can translate these into the following two command strings to get the job done:

    #main, "up; goto 155 35, down, circlefilled 5"
    #main, "up; goto 205 85, down, circlefilled 5"

So now, lets move on to our next, the third dice. First we need to calculate the offset. We know that each dice requires 120 pixels, and the initial offset was 20 pixels. So the third dice offset should equal 20+120+120, or 260. Now we need the same dots as we did in the two, as well as a center dot. The math is basically the same:

Top-left dot:

   X: 260 + 15 = 275
   Y: 20 + 15 = 35

Center dot:

   X: 260 + 15+25 = 300
   Y: 20 + 15 + 25 = 60

Bottom-right dot:

   X: 260 + 15 + 25 + 25 = 325
   Y: 20 + 15 + 25 +25 = 85

We can continue this way until we have calculated the locations of all the dots. It takes a bit of planning and some math, but it is really pretty easy to understand. I have completed the code to fill all six faces of our dice display. This is in response to the challenge from the previous installment of this series. I hope you also tried to do this. If not, maybe now you will take a shot before looking at the answer. To check your work, please refer to Appendix A for the source code.

Go To Part 2, Command Buttons and Events


Home

Tip Corner: Using

Game Programming

Round Buttons

Rotating Objects

LBW: Book Marks

Slide Puzzle

Speech DLL

Addresses

Beginners Programming

Newsletter help

Index